﻿using System;
using System.Linq;
using System.Text;
using System.Collections.ObjectModel;
using System.Windows.Input;
using Microsoft.Practices.Composite.Presentation.Commands;

namespace Elentok.Common.Wpf.ViewModels.Dialogs
{
  /// <summary>
  /// Defines the requirements from the buttons dialog viewmodel
  /// </summary>
  public interface IButtonsDialogViewModel : IDialogViewModel
  {
    /// <summary>
    /// Gets or sets the displayed message
    /// </summary>
    string Message { get; set; }

    /// <summary>
    /// Gets the collection of the dialog's buttons
    /// </summary>
    ObservableCollection<IButtonViewModel> Buttons { get; }

    /// <summary>
    /// Gets the selected button
    /// </summary>
    IButtonViewModel SelectedButton { get; }

    /// <summary>
    /// Gets the command that is executed when a button is clicked
    /// </summary>
    ICommand ButtonCommand { get; }
  }

  /// <summary>
  /// The buttons dialog view model
  /// </summary>
  public class ButtonsDialogViewModel : DialogViewModelBase, IButtonsDialogViewModel
  {
    #region Private Fields
    private string message;
    #endregion

    /// <summary>
    /// Initializes a new instance of the <see cref="ButtonsDialogViewModel"/> class.
    /// </summary>
    public ButtonsDialogViewModel()
    {
      this.Buttons = new ObservableCollection<IButtonViewModel>();
      this.ButtonCommand = new DelegateCommand<IButtonViewModel>(this.ExecuteButtonCommand, this.CanExecuteButtonCommand);
    }

    #region IButtonsDialogViewModel Members

    /// <summary>
    /// Gets or sets the message
    /// </summary>
    public string Message
    {
      get
      {
        return this.message;
      }
      set
      {
        if (this.message == value)
          return;

        OnPropertyChanging("Message");
        this.message = value;
        OnPropertyChanged("Message");
      }
    }

    /// <summary>
    /// Gets the collection of the dialog's buttons
    /// </summary>
    public ObservableCollection<IButtonViewModel> Buttons { get; private set; }

    /// <summary>
    /// Gets the selected button
    /// </summary>
    public IButtonViewModel SelectedButton { get; private set; }

    /// <summary>
    /// Gets the command that is executed when a button is clicked
    /// </summary>
    public ICommand ButtonCommand { get; private set; }

    #endregion

    #region Button Command Execute/CanExecute

    private void ExecuteButtonCommand(IButtonViewModel button)
    {
      this.SelectedButton = button;
      Close(button.DialogResult);
    }

    private bool CanExecuteButtonCommand(IButtonViewModel button)
    {
      return button.IsEnabled;
    }

    #endregion
  }

  /// <summary>
  /// Defines a button's view model
  /// </summary>
  public interface IButtonViewModel : IViewModel
  {
    /// <summary>
    /// Gets or sets the header of the button
    /// </summary>
    string Header { get; set; }

    /// <summary>
    /// Gets or sets the dialog result of this button
    /// </summary>
    bool DialogResult { get; set; }

    /// <summary>
    /// Gets or sets whether this button is enabled
    /// </summary>
    bool IsEnabled { get; set; }

    /// <summary>
    /// Gets or sets whether this button is the default
    /// </summary>
    bool IsDefault { get; set; }
  }

  /// <summary>
  /// A button's view model
  /// </summary>
  public class ButtonViewModel : ViewModelBase, IButtonViewModel
  {
    #region Private Fields

    private string header;
    private bool isEnabled = true;
    private bool dialogResult = true;
    private bool isDefault = false;

    #endregion

    #region IButtonViewModel Members

    /// <summary>
    /// Gets or sets the header
    /// </summary>
    public string Header
    {
      get
      {
        return this.header;
      }
      set
      {
        if (this.header == value)
          return;

        OnPropertyChanging("Header");
        this.header = value;
        OnPropertyChanged("Header");
      }
    }

    /// <summary>
    /// Gets or sets the isEnabled
    /// </summary>
    public bool IsEnabled
    {
      get
      {
        return this.isEnabled;
      }
      set
      {
        if (this.isEnabled == value)
          return;

        OnPropertyChanging("IsEnabled");
        this.isEnabled = value;
        OnPropertyChanged("IsEnabled");
      }
    }

    /// <summary>
    /// Gets or sets the dialogResult
    /// </summary>
    public bool DialogResult
    {
      get
      {
        return this.dialogResult;
      }
      set
      {
        if (this.dialogResult == value)
          return;

        OnPropertyChanging("DialogResult");
        this.dialogResult = value;
        OnPropertyChanged("DialogResult");
      }
    }

    /// <summary>
    /// Gets or sets the isDefault
    /// </summary>
    public bool IsDefault
    {
      get
      {
        return this.isDefault;
      }
      set
      {
        if (this.isDefault == value)
          return;

        OnPropertyChanging("IsDefault");
        this.isDefault = value;
        OnPropertyChanged("IsDefault");
      }
    }

    #endregion

    /// <summary>
    /// Returns a <see cref="System.String"/> that represents the current instance
    /// </summary>
    /// <returns></returns>
    public override string ToString()
    {
      return "ButtonViewModel(" + this.header + ")";
    }
  }

}